<?php
/**
 * Created by PhpStorm.
 * User: ownfi
 * Date: 2017-04-08
 * Time: 10:28
 */

namespace App\Services\Impl;


use App\Common\Constant\Params;
use App\Common\Constant\Status;
use App\Models\MasterCash;
use App\Models\MasterFund;
use App\Models\MasterTradeLog;
use App\Models\MasterWallet;
use App\Models\MerchantTradeLog;
use App\Models\Order;
use App\Models\OrderRefund;
use App\Models\OrderStatus;
use App\Services\Factory\PaymentFactory;
use App\Services\IMasterLogService;
use App\Services\IPayService;
use App\Services\IWalletService;
use DB;
use Log;

class PayServiceImpl implements IPayService
{
    private $payer;

    private $masterLogService;

    /**
     * PayServiceImpl constructor.
     */
    public function __construct(IMasterLogService $masterLogService)
    {
        $this->masterLogService = $masterLogService;
    }


    public function setPaymentMethod($payment_method)
    {
        $this->payer = PaymentFactory::factory($payment_method);
    }

    public function doReturnFund($trade_number, $payee_real_name, $payee_account, $amount)
    {
        if (empty($this->payer)){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,status(Status::PAYMENT_METHOD_NOTSET)));
            return false;
        }
        return $this->handlePaymentSuccess($trade_number);
//        $transaction_id = $this->payer->transfer($trade_number, $payee_real_name, $payee_account, $amount,config('app.name')."退还质保金");
//        if (!$transaction_id){
//            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'return fund fail'));
//            return false;
//        }
//        return $this->handlePaymentSuccess($trade_number,$transaction_id);
    }

    public function doCash($trade_number, $payee_real_name, $payee_account, $amount)
    {
        if (empty($this->payer)){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,status(Status::PAYMENT_METHOD_NOTSET)));
            return false;
        }
        $transaction_id = $this->payer->transfer($trade_number, $payee_real_name, $payee_account, $amount,config('app.name')."钱包余额提现");
        if (!$transaction_id){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'cash fail'));
            return false;
        }
        return $this->handlePaymentSuccess($trade_number,$transaction_id);
    }

    public function doRefund($trade_number, $pay_trade_number, $transaction_id, $amount)
    {
        if (empty($this->payer)){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,status(Status::PAYMENT_METHOD_NOTSET)));
            return false;
        }
        $ret = $this->payer->refund($trade_number, $pay_trade_number, $transaction_id, $amount);
        if (!$ret){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'refund fail'));
            return false;
        }
        return $this->handleMerchantPaymentSuccess($trade_number,$transaction_id);
    }

    public function log($message)
    {
        if (!empty($this->payer)){
            $this->payer->log($message);
        }else{
            Log::info('payment log: '.$message);
        }
    }

    public function handleNotify()
    {
        $this->log('handleNotify');
        if (empty($this->payer)){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,status(Status::PAYMENT_METHOD_NOTSET)));
            return false;
        }
        list($trade_number,$payment_gate_number,$attach) = $this->payer->notify();//此处返回支付成功状态下的数据，并且已经把返回参数打印出来
        $this->log('trade_number：'.$trade_number.' payment_gate_number：'.$payment_gate_number);
        if ($trade_number){
            $model = MasterTradeLog::where('trade_number',$trade_number)->first();
            if (!$model){
                Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss trade log'));
                return false;
            }

            $attach = json_decode($attach);
            switch ($attach->pay_method){
                case Params::PAY_METHOD_WEIXIN:
                    $model->wxpay_no = $payment_gate_number;
                    break;
                case Params::PAY_METHOD_ALIPAY:
                    $model->alipay_no = $payment_gate_number;
                    break;
            }

            $model->status = Params::TRADE_STATUS_SUCCESS;
            $ret = $model->save();

            if ($ret){
                $this->handlePaymentSuccess($trade_number);
            }
        }
    }

    public function handleMerchantPaymentSuccess($trade_number,$transaction_id = null)
    {
        $trade_log = MerchantTradeLog::where('trade_number',$trade_number)->first();
        if (!$trade_log){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss trade log'));
            return false;
        }
        if ($trade_log->status != Params::TRADE_STATUS_SUCCESS){
            $trade_log->status = Params::TRADE_STATUS_SUCCESS;
        }
        if ($transaction_id){
            $trade_log->alipay_no = $transaction_id;
        }
        $trade_log->save();
        $this->log(Params::$MERCHANT_TRADE_TYPE[$trade_log->status]);

        $ret = false;
        switch ($trade_log->type){
            case Params::MERCHANT_TRADE_TYPE_RECHARGE://充值
                break;
            case Params::MERCHANT_TRADE_TYPE_ORDER://下单
                break;
            case Params::MERCHANT_TRADE_TYPE_CANCEL://退单
                break;
            case Params::MERCHANT_TRADE_TYPE_FILL://补款
                break;
            case Params::MERCHANT_TRADE_TYPE_REFUND://退款
                $ret = OrderRefund::find($trade_log->order_number_list)->each(function($item,$key){
                    return $item->update([
                        'refund_success_time'=>time()
                    ]);
                });
                break;
            case Params::MERCHANT_TRADE_TYPE_BATCH_ORDER://批量付款
                break;
            default:
                return false;
        }

        return $ret;
    }

    public function handlePaymentSuccess($trade_number,$transaction_id = null)
    {
        $this->log('handlePaymentSuccess');
        $trade_log = MasterTradeLog::where('trade_number',$trade_number)->first();
        if (!$trade_log){
            Log::error(sprintf('%s/%s::%s[%d] %s',__NAMESPACE__,__CLASS__,__FUNCTION__,__LINE__-2,'miss trade log'));
            return false;
        }
        if ($trade_log->status != Params::TRADE_STATUS_SUCCESS){
            $trade_log->status = Params::TRADE_STATUS_SUCCESS;
        }
        if ($transaction_id){
            $trade_log->transaction_id = $transaction_id;
        }
        $trade_log->save();
        $this->log(Params::$TRADE_STATUS[$trade_log->status]);

        $ret = false;
        switch ($trade_log->type){
            case Params::TRADE_TYPE_ASSURE://缴纳诚信保证金
                break;
            case Params::TRADE_TYPE_ORDER://订单完成收款入账
                $ret = OrderStatus::where('order_id',$trade_log->order_number)->take(1)->update([
                    'merchant_status'=>Params::ORDER_MERCHANT_STATUS_SUCCESS,
                    'master_status'=>Params::ORDER_MASTER_STATUS_SUCCESS,
                    'order_success_time'=>time()
                ]);
                break;
            case Params::TRADE_TYPE_CASH://提现
                $ret = MasterCash::find($trade_log->order_number)->update([
                    'pay_time'=>time()
                ]);
                break;
            case Params::TRADE_TYPE_REFUND://商家要求退款
                $ret = OrderRefund::find($trade_log->order_number)->update([
                    'refund_success_time'=>time()
                ]);
                break;
            case Params::TRADE_TYPE_PUNISH://罚款
                $ret = true;
//                Order::find($trade_log->order_number);
                break;
            case Params::TRADE_TYPE_RETURN_ASSURE://退还诚信保证金
                $ret = MasterFund::find($trade_log->order_number)->update([
                        'status'=>Params::MASTER_FUND_PASS,
                        'pay_time'=>time()
                    ]);
                break;
            default:
                return false;
        }
        return $ret;
    }

}